{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Pacemaker\n",
    "\n",
    "*  Pacemakerとは\n",
    "    * HA(高可用性)クラスタソフト\n",
    "      * 故障を検知した場合，待機系へサービスを引き継がせること（フェイルオーバ）によってサービスのダウンタイムを最小限にする事が可能\n",
    "      * Heartbeatの後継ソフトウェア\n",
    "      * リソース制御機能のみ。クラスタ制御機能を持つソフトウェアと組み合わせる必要がある(Heartbeat,Corosyncなど)\n",
    "\n",
    "* 歴史\n",
    "      * 2003 Heartbeat ver1 : 相手ノードの監視など、クラスタ制御機能のみ\n",
    "      * 2005 Heartbeat ver2 : リソース制御機能（CRM：Cluster Resource Manager)追加\n",
    "      * 2008 Pacemaker ver1 : Heartbeatからリソース制御機能を独立させる\n",
    "      * ???? Heartbert ver3 : クラスタ制御機能のみメンテナンスされている\n",
    "\n",
    "## 基本機能\n",
    "\n",
    "* クラスタ制御機能 (Heartbeat担当)\n",
    "   * 機能例\n",
    "     * クラスタ状態を伝播する通信\n",
    "     * クラスタへのノード参加判断\n",
    "     * クラスタノード間における情報の同期\n",
    "     * 一定間隔で相手ノードと通信し生死を確認\n",
    "   * ハートビート通信\n",
    "     * 生死確認の通信はインターコネクト通信のこと\n",
    "       * これが途絶えたときは相手が故障したと判断し，フェイルオーバ処理を実施\n",
    "\n",
    "* リソース制御機能 (Pacemaker担当)\n",
    " * 一定間隔でリソースを監視し，正常動作していないと判断した場合にリソースのフェイルオーバ処理を行う\n",
    "   * リソース\n",
    "     * Pacemakerが制御対象とするアプリケーション(Apache,MySQLなど)，ネットワーク，ディスク等のこと\n",
    "     * リソースをリソースエージェントを介して起動（start），停止（stop），監視（monitor）を実行しリソース制御を行う\n",
    "   * リソースエージェント\n",
    "     * リソースとPacemakerを仲介するプログラムで，主にシェルスクリプトで作成されている。自作もできる。\n",
    "\n",
    "## リソースの種類\n",
    "\n",
    "* Primitive\n",
    "    * 通常のAct-Standby構成で用いるリソース\n",
    "    * どこか一カ所のノードで動くことができる\n",
    "        * クラスタ全体のある1ノードだけで動いていればよいリソースに使用\n",
    "        * リソースが故障すれば、他のノードにフェールオーバーさせることができる\n",
    "    * データベースやメールサーバのようなものをHAクラスタリングする場合は通常このリソースを定義\n",
    "* Clone\n",
    "    * Primitive リソースを複数のノードで動作させたい場合に使用\n",
    "    * 定義方法\n",
    "        * まずPrimitive を定義し、それをClone化する\n",
    "* Master/Slave\n",
    "    * Clone リソースをさらに発展させたもの\n",
    "        * Cloneリソースで親子の関係があるリソースに使用\n",
    "    * 定義方法\n",
    "        * まずPrimitive を定義\n",
    "        * Master/Slave化する\n",
    "    * リソースの起動・停止操作\n",
    "        * start, stop \n",
    "            * Primitive, Clone 用のRAに実装されている\n",
    "        * promote(昇格), demote(降格)\n",
    "            * <font color=\"red\">親に昇格させたり子供に降格させる</font> Master/Slave専用の操作\n",
    "* Group\n",
    "    * 複数のPrimitiveリソースを１つのグループとしてまとめたリソース\n",
    "    * 同じグループとなったPrimitiveリソースは<font color=\"red\">必ず同じノードで、定義された順番に起動／停止</font>\n",
    "        * Pacemaker内部の動作としては「colocation(同居)制約」と「order(順序)制約」の両制約をかけたのと同等\n",
    "        \n",
    "\n",
    "## 参考\n",
    "\n",
    "* [第1回　Pacemakerの歴史を見てみよう！](http://gihyo.jp/admin/serial/01/pacemaker/0001?page=2)\n",
    "\n",
    "\n",
    "## crmのshowコマンド解説\n",
    "\n",
    "```\n",
    "crm(live)configure# show\n",
    "================================================\n",
    "node $id=\"10c76ad1-e4c4-441d-a62e-bec05e25f882\" drbd01\n",
    "node $id=\"ea4ec1c7-bdd3-4bf7-9177-c8d2a1569389\" drbd02\n",
    "\n",
    "\n",
    "### primitiveコマンド書式\n",
    "primitive リソースID RA(リソースエージェント)名  [params RAに渡すパラメータ...] [op start|stop|monitor オペレーション時の設定...]\n",
    "\n",
    "---------\n",
    "primitive res_drbd0 ocf:linbit:drbd \\\n",
    "        params drbd_resource=\"r0\" drbdconf=\"/etc/drbd.conf\" \\\n",
    "        op monitor interval=\"20s\"\n",
    "\n",
    "※ pacemakerでdrbdの起動や停止を制御する。chkconfig drbd offにしておくこと。\n",
    "https://www.drbd.jp/users-guide/s-pacemaker-crm-drbd-backed-service.html\n",
    "\n",
    "\n",
    "リソースID : res_drbd0\n",
    "RA名 : ocf:linbit:drbd (/usr/lib/ocf/resource.d/linbit/drbdに実体のシェルスクリプトがある)\n",
    "params\n",
    "  drbd_resource=\"r0\" : drbdのリソースを指定\n",
    "  drbdconf=\"/etc/drbd.conf\" :  drbdのconfファイルを指定\n",
    "\n",
    "シェルスクリプト中でこれらのパラメータが利用される\n",
    "### /usr/lib/ocf/resource.d/linbit/drbd\n",
    "...\n",
    "\n",
    "<parameters>\n",
    "...\n",
    "<parameter name=\"drbd_resource\" unique=\"1\" required=\"1\">\n",
    "...\n",
    "</parameters>\n",
    "\n",
    "...\n",
    "\n",
    "<parameters>\n",
    "...\n",
    "<parameter name=\"drbdconf\">\n",
    "...\n",
    "</parameters>\n",
    "...\n",
    "\n",
    "op monitor interval=\"20s\" : オペレーションの繰り返し間隔\n",
    "\n",
    "\n",
    "---------\n",
    "primitive res_filesystem ocf:heartbeat:Filesystem \\\n",
    "        params device=\"/dev/drbd0\" fstype=\"ext4\" directory=\"/var/share\" \\\n",
    "        op monitor interval=\"20s\"\n",
    "\n",
    "※ pacemakerでマウントを制御する。ここで制御するファイルシステムは/etc/fstabに書いてはいけない\n",
    "\n",
    "リソースID : res_filesystem\n",
    "RA名 : ocf:heartbeat:Filesystem (/usr/lib/ocf/resource.d/heartbeat/Filesystemに実体のシェルスクリプトがある)\n",
    "params\n",
    "  device=\"/dev/drbd0\" : Filesystemを指定\n",
    "  fstype=\"ext4\" : fstypeを指定\n",
    "  directory=\"/var/share\" : マウントポイントを指定\n",
    "\n",
    "---------\n",
    "primitive res_ip ocf:heartbeat:IPaddr \\\n",
    "        params ip=\"10.136.3.167\" cidr_netmask=\"17\" nic=\"eth0\" \\\n",
    "        op monitor interval=\"10s\"\n",
    "\n",
    "※ VIPの付け替えを制御する。ここで制御するアドレスは/etc/sysconfig/network-scripts/ifcfg-eth0:1などのファイルを作ってはいけない。\n",
    "\n",
    "リソースID : res_ip\n",
    "RA名 : ocf:heartbeat:IPaddr (/usr/lib/ocf/resource.d/heartbeat/IPaddrに実体のシェルスクリプトがある)\n",
    "params\n",
    "  ip=\"10.136.3.167\" : IPアドレスを指定\n",
    "  cidr_netmask=\"17\" : netmaskを指定\n",
    "  nic=\"eth0\" : nicを指定\n",
    "\n",
    "---------\n",
    "group rg_drbd res_ip res_filesystem\n",
    "\n",
    "※ primitiveで定義した個々のリソースをグループ化する。グループ化すると以下の制御が行われる\n",
    "   * 常に同一サーバで起動する。\n",
    "   * groupコマンドに指定した順にリソースを起動する。またその逆順に停止する。\n",
    "\n",
    "### groupコマンド書式\n",
    "group グループID リソースID\n",
    "\n",
    "グループID : rg_drbd\n",
    "リソースID : res_ip, res_filesystem\n",
    "\n",
    "つまり、VIPの付与とファイルシステムのマウントは同一のサーバ上で行われる\n",
    "\n",
    "---------\n",
    "ms ms_drbd0 res_drbd0 \\\n",
    "        meta master-max=\"1\" master-node-max=\"1\" clone-max=\"2\" clone-node-max=\"1\" notify=\"true\"\n",
    "\n",
    "※ msコマンドでmaster/slaveリソースを定義\n",
    "\n",
    "### msコマンド書式\n",
    "ms マスターID リソースID\n",
    "\n",
    "マスターID : ms_drbd0\n",
    "リソースID : res_drbd0\n",
    "meta (msリソースの動作設定)\n",
    "  master-max=\"1\" : masterになれるリソース数\n",
    "  master-node-max=\"1\" : 1つのノードでmasterになれるリソース数\n",
    "  clone-max=\"2\" : 生成するインスタンス数 (2ノード構成であれば2を指定)\n",
    "  clone-node-max=\"1\" : 一つのノードで同時に起動するインスタンス数\n",
    "  notify=\"true\" : DRBDはnotifyアクションを使うのでtrueにする\n",
    "\n",
    "http://www.slideshare.net/tatsuyaw/pacemaker-osc2014tokyo-31882542\n",
    "\n",
    "---------\n",
    "colocation c_rg_drbd_on_drbd0 inf: rg_drbd ms_drbd0:Master\n",
    "\n",
    "リソースの同居制約を定義する\n",
    "\n",
    "### colocationコマンド書式\n",
    "colocation コロケーションID <score>: リソースA:役割 リソースB:役割 ...\n",
    "\n",
    "コロケーションID : c_rg_drbd_on_drbd0\n",
    "スコア : inf　リソースAが故障時にリソースBも影響を受ける  (スコアが0の場合は受けない)\n",
    "\n",
    "rg_drbd ms_drbd0:Master\n",
    "\n",
    "つまり、DRBDがMaster状態のサーバでrg_drbdが適用される(VIP付与、ファイルシステムマウント)\n",
    "http://www.slideshare.net/tatsuyaw/pacemaker-osc2014tokyo-31882542\n",
    "\n",
    "---------\n",
    "order o_drbd_befor_rg_drbd inf: ms_drbd0:promote rg_drbd:start\n",
    "\n",
    "### orderコマンド書式\n",
    "order オーダーID <score>: リソースA:アクション リソースB:アクション ...\n",
    "\n",
    "オーダーID : o_drbd_befor_rg_drbd\n",
    "スコア : inf\n",
    "\n",
    "リソースAが昇格(promote)してからリソースBを起動(start)(VIP付与、ファイルシステムマウント)\n",
    "http://www.slideshare.net/tatsuyaw/pacemaker-osc2014tokyo-31882542\n",
    "\n",
    "\n",
    "---------\n",
    "property $id=\"cib-bootstrap-options\" \\\n",
    "        dc-version=\"1.0.13-a83fae5\" \\\n",
    "        cluster-infrastructure=\"Heartbeat\" \\\n",
    "        stonith-enabled=\"false\" \\　 ### STONISH機能無効 http://gihyo.jp/admin/serial/01/pacemaker/0003\n",
    "        no-quorum-policy=\"ignore\" \\ ### 2台構成のときはignoreでよい\n",
    "        default-resource-stickiness=\"200\" ###  通常は大きな値にして自動フェイルバックを無効にする http://linux-ha.osdn.jp/wp/archives/3786/3\n",
    "\n",
    "http://gihyo.jp/admin/serial/01/pacemaker/0003\n",
    "\n",
    "================================================\n",
    "```\n",
    "\n",
    "### 参考\n",
    "* [動かして理解するPacemaker ～CRM設定編～ その２](http://linux-ha.osdn.jp/wp/archives/3855#primitive)\n",
    "* [PacemakerのMaster/Slave構成の基本と事例紹介(DRBD、PostgreSQLレプリケーション) ](https://www.slideshare.net/tatsuyaw/pacemaker-osc2014tokyo-31882542)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## crmコマンド\n",
    "\n",
    "* crm resource list\n",
    "    * 全てのリソースのリストを取得する\n",
    "    * crm resource statusと同じ\n",
    "\n",
    "```\n",
    "$ sudo crm resource list\n",
    "================================================\n",
    " Resource Group: rg_drbd\n",
    "     res_ip     (ocf::heartbeat:IPaddr):        Started\n",
    "     res_filesystem     (ocf::heartbeat:Filesystem):    Started\n",
    " Master/Slave Set: ms_drbd0\n",
    "     Masters: [ drbd01 ]\n",
    "     Slaves: [ drbd02 ]\n",
    "================================================\n",
    "```\n",
    "\n",
    "* crm resource demote (リソース)\n",
    "    * リソースをSlaveに降格する\n",
    "\n",
    "```\n",
    "$ sudo crm resource demote ms_drbd0\n",
    "$ sudo crm resource list\n",
    "================================================\n",
    " Resource Group: rg_drbd\n",
    "     res_ip     (ocf::heartbeat:IPaddr):        Stopped\n",
    "     res_filesystem     (ocf::heartbeat:Filesystem):    Stopped\n",
    " Master/Slave Set: ms_drbd0\n",
    "     Slaves: [ drbd01 drbd02 ]\n",
    "================================================\n",
    "```\n",
    "\n",
    "* crm resource promote (リソース)\n",
    "    * リソースをMasterに降格する\n",
    "\n",
    "```\n",
    "$ sudo crm resource promote ms_drbd0\n",
    "$ sudo crm resource list\n",
    "================================================\n",
    " Resource Group: rg_drbd\n",
    "     res_ip     (ocf::heartbeat:IPaddr):        Started\n",
    "     res_filesystem     (ocf::heartbeat:Filesystem):    Started\n",
    " Master/Slave Set: ms_drbd0\n",
    "     Masters: [ drbd01 ]\n",
    "     Slaves: [ drbd02 ]\n",
    "================================================\n",
    "```\n",
    "\n",
    "### 参考\n",
    "* [7.4 クラスタリソースの管理](https://www.suse.com/ja-jp/documentation/sle_ha/book_sleha/data/sec_ha_config_crm.html?view=print)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## crm_resourceコマンド\n",
    "\n",
    "* crm_resource -r rg_drbd -M\n",
    "    * MasterとSlaveを切り替える\n",
    "    * マスターが現在の位置から別の位置に移動する\n",
    "    * -rオプション\n",
    "        * リソースを指定\n",
    "* crm_resource -r rg_drbd -U\n",
    "    * Masterに昇格できない制約を解除する\n",
    "        * -MでMaster,Slaveを切り替えた場合group_masterが永遠に開始しなくなるため障害が発生しても自動で切り替わらない\n",
    "        * -> -Uを実行して制約(location cli-standby-rg_drbd～)を解除する"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## ステータス解読"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "============\n",
    "Last updated: Wed Jul 19 13:13:58 2017\n",
    "Stack: Heartbeat\n",
    "Current DC: drbd02 (519baeac-3787-4f4a-8361-fb3e1f84cb21) - partition with quorum\n",
    "Version: 1.0.13-a83fae5\n",
    "2 Nodes configured, unknown expected votes\n",
    "2 Resources configured.\n",
    "============\n",
    "\n",
    "Online: [ drbd01 drbd02 ]\n",
    "\n",
    " Master/Slave Set: ms_drbd0\n",
    "     Masters: [ drbd01 drbd02 ]\n",
    " Resource Group: rg_drbd\n",
    "     res_ip     (ocf::heartbeat:IPaddr):        Started FAILED [ drbd01 drbd02 ]\n",
    "     res_filesystem     (ocf::heartbeat:Filesystem):    Started drbd01 (unmanaged) FAILED\n",
    "\n",
    "Node Attributes:\n",
    "* Node drbd01:\n",
    "    + master-res_drbd0:0                : 10000\n",
    "    + drbd02-eth0                  : up\n",
    "* Node drbd02:\n",
    "    + master-res_drbd0:1                : 10000\n",
    "    + drbd01-eth0                  : up\n",
    "\n",
    "Failed actions:\n",
    "    res_filesystem_stop_0 (node=drbd01, call=21, rc=1, status=complete): unknown error\n",
    "    res_ip_monitor_10000 (node=drbd02, call=12, rc=7, status=complete): not running\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* Current DC: drbd02\n",
    "    * drbd02がクラスタの指揮をとっている\n",
    "    * クラスタに参加しているサーバのどれか(ここではdrbd01,drbd02)であればOK\n",
    "* Masters: [ drbd01 drbd02 ]\n",
    "    * drbd01, drbd02両方ともMasterになっている状態"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
